package com.lyh.notes.service.Impl;

import com.lyh.notes.annotation.NeedLogin;
import com.lyh.notes.mapper.CategoryMapper;
import com.lyh.notes.mapper.NoteMapper;
import com.lyh.notes.mapper.UserMapper;
import com.lyh.notes.model.base.ApiResponse;
import com.lyh.notes.model.base.EmptyVO;
import com.lyh.notes.model.base.Pagination;
import com.lyh.notes.model.dto.note.CreateNoteRequest;
import com.lyh.notes.model.dto.note.NoteQueryRequest;
import com.lyh.notes.model.dto.note.UpdateNoteRequest;
import com.lyh.notes.model.entity.Category;
import com.lyh.notes.model.entity.Note;
import com.lyh.notes.model.entity.User;
import com.lyh.notes.model.vo.note.*;
import com.lyh.notes.scope.RequestScopeData;
import com.lyh.notes.service.*;
import com.lyh.notes.utils.ApiResponseUtil;
import com.lyh.notes.utils.MarkdownUtil;
import com.lyh.notes.utils.PaginationUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;

import javax.validation.Valid;
import java.util.*;

@Slf4j
@Service
public class NoteServiceImpl implements NoteService {

    @Autowired
    private NoteMapper noteMapper;

    @Autowired
    private UserService userService;


    @Autowired
    private NoteLikeService noteLikeService;

    @Autowired
    private CollectionNoteService collectionNoteService;

    @Autowired
    private RequestScopeData requestScopeData;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private CategoryMapper categoryMapper;
    @Autowired
    private UserMapper userMapper;

    @Override
    public ApiResponse<List<NoteVO>> getNotes(@Valid@RequestBody NoteQueryRequest request) {
        // 得到notes
        int offset= PaginationUtil.calculateOffset(request.getPage(),request.getPageSize());
        List<Note>notes=noteMapper.findByQueryParams(request,offset,request.getPageSize());
        int total=noteMapper.countNotes(request);
        Pagination pagination=new Pagination(request.getPage(),request.getPageSize(),total);
        if(notes==null){
            return ApiResponseUtil.success("当前无笔记");
        }
        // 得到所有笔记的作者并去重,之后得到他们的所需要的信息, 用HashMap映射作者ID和作者信息
        List<Long>usersId=notes.stream().map(Note::getAuthorId).distinct().toList();
        Map<Long,User>userMapByIds=userService.getUserMapByIds(usersId);

        // 得到所有笔记的类别并去重,之后得到他们的所需要的信息, 用HashMap映射类别ID和类别信息
        List<Integer>categoryIds=notes.stream().map(Note::getCategoryId).distinct().toList();
        Map<Integer, Category> categoryMapByIds =categoryService.getCategoryMapByIds(categoryIds);

        // 得到当前登录状态的用户所有点赞和收藏的笔记列表,用HashSet记录这些笔记的ID
        Set<Integer> userLikedNoteIds;
        Set<Integer> userCollectedNoteIds;
        List<Integer>noteIds=notes.stream().map(Note::getNoteId).toList();
        if (requestScopeData.isLogin() && requestScopeData.getUserId() != null) {
            Long currentUserId = requestScopeData.getUserId();
            userLikedNoteIds = noteLikeService.findUserLikedNoteIds(currentUserId, noteIds);
            userCollectedNoteIds = collectionNoteService.findUserCollectedNoteIds(currentUserId, noteIds);
        } else {  // 未登录状态直接设置为空集合
            userLikedNoteIds = Collections.emptySet();
            userCollectedNoteIds = Collections.emptySet();
        }
        // 对于每一个note,根据noteID绑定其余信息形成NoteVO
        try {
            List<NoteVO>noteVOS=notes.stream().map(note -> {
                NoteVO noteVO=new NoteVO();
                BeanUtils.copyProperties(note,noteVO);
                User author= userMapByIds.get(note.getAuthorId());
                if(author!=null){
                    NoteVO.SimpleAuthorVO simpleAuthorVO=new NoteVO.SimpleAuthorVO();
                    BeanUtils.copyProperties(author,simpleAuthorVO);
                    log.info(simpleAuthorVO.toString());
                    noteVO.setAuthor(simpleAuthorVO);
                }
                Integer categoryId=note.getCategoryId();
                if(categoryId!=null){
                    NoteVO.SimpleCategoryVO simpleCategoryVO=new NoteVO.SimpleCategoryVO();
                    Category category=categoryMapByIds.get(categoryId);
                    simpleCategoryVO.setCategoryId(category.getCategoryId());
                    simpleCategoryVO.setCategoryName(category.getName());
                    log.info(simpleCategoryVO.toString());
                    noteVO.setCategory(simpleCategoryVO);
                }
                //是否点赞或收藏
                NoteVO.UserActionsVO userActionsVO=new NoteVO.UserActionsVO();
                userActionsVO.setIsCollected(userCollectedNoteIds.contains(note.getNoteId()));
                userActionsVO.setIsLiked(userLikedNoteIds.contains(note.getNoteId()));
                noteVO.setUserActions(userActionsVO);

                if(MarkdownUtil.needCollapsed(noteVO.getContent())){
                    noteVO.setNeedCollapsed(true);
                    noteVO.setDisplayContent(MarkdownUtil.extractIntroduction(noteVO.getContent()));
                }else{
                    noteVO.setNeedCollapsed(false);
                }

                return noteVO;
                }
            ).toList();
            return ApiResponseUtil.success("获取笔记列表成功", noteVOS,pagination);
        } catch (Exception e) {
            return ApiResponseUtil.error("获取笔记列表失败");
        }
    }

    @Override
    @NeedLogin
    public ApiResponse<CreateNoteVO> createNote(CreateNoteRequest request) {
        Long userId = requestScopeData.getUserId();
        if(request.getCategoryId()!=null)
        {
            Category category = categoryMapper.findById(request.getCategoryId());
            if (category == null) {
                return ApiResponseUtil.error("categoryId 对应的分类不存在");
            }
        }
        Note note=new Note();
        BeanUtils.copyProperties(request,note);
        note.setAuthorId(userId);
        try {
            noteMapper.insert(note);
            CreateNoteVO createNoteVO = new CreateNoteVO();
            createNoteVO.setNoteId(note.getNoteId());
            return ApiResponseUtil.success("创建笔记成功", createNoteVO);
        } catch (Exception e) {
            return ApiResponseUtil.error("创建笔记失败");
        }

    }


    @Override
    @NeedLogin
    public ApiResponse<EmptyVO> updateNote(Integer noteId, UpdateNoteRequest request) {
        Note note=noteMapper.findById(noteId);
        if(note==null){
            return ApiResponseUtil.error("笔记不存在");
        }
        if(request.getCategoryId()!=null)
        {
            Category category = categoryMapper.findById(request.getCategoryId());
            if (category == null) {
                return ApiResponseUtil.error("categoryId 对应的分类不存在");
            }
        }
        Long userId = requestScopeData.getUserId();
        log.info(String.valueOf(userId));
        if(!userId.equals(note.getAuthorId())){
            return ApiResponseUtil.error("无权限修改他人笔记");
        }
        BeanUtils.copyProperties(request,note);
        try {
            noteMapper.update(note);
            return ApiResponseUtil.success("更新成功");
        } catch (Exception e) {
            return ApiResponseUtil.error("更新失败");
        }
    }

    @Override
    @NeedLogin
    public ApiResponse<EmptyVO> deleteNote(Integer noteId) {
        Note note=noteMapper.findById(noteId);
        if(note==null){
            return ApiResponseUtil.error("笔记不存在");
        }
        Long userId = requestScopeData.getUserId();
        User curUser=userMapper.findUserById(userId);
        if(curUser.getIsAdmin()==0){
            if(!userId.equals(note.getAuthorId())){
                return ApiResponseUtil.error("无权限修改他人笔记");
            }
        }
        try {
            noteMapper.deleteById(noteId);
            return ApiResponseUtil.success("删除成功");
        } catch (Exception e) {
            return ApiResponseUtil.error("删除失败");
        }
    }

    @Override
    @NeedLogin
    public ApiResponse<DownloadNoteVO> downloadNote() {
        // 获得当前用户笔记
        Long userId = requestScopeData.getUserId();
        List<Note> noteList = noteMapper.findByAuthorId(userId);
        if(noteList==null|| noteList.isEmpty()){
            return ApiResponseUtil.error("未找到笔记");
        }
        // 生成markdown并返回
        StringBuilder markdown=new StringBuilder();
        for(Note note:noteList){
            markdown.append(note.getContent()).append("\n");
            markdown.append("\n");
        }
        DownloadNoteVO downloadNoteVO=new DownloadNoteVO();
        downloadNoteVO.setMarkdown(markdown.toString());
        return ApiResponseUtil.success("生成笔记成功",downloadNoteVO);

    }

    @Override
    public ApiResponse<List<NoteRankListItem>> submitNoteRank() {
        return ApiResponseUtil.success("获取笔记排行榜成功", noteMapper.submitNoteRank());
    }

    @Override
    @NeedLogin
    public ApiResponse<List<NoteHeatMapItem>> submitNoteHeatMap() {
        Long userId = requestScopeData.getUserId();
        return ApiResponseUtil.success("获取笔记热力图成功", noteMapper.submitNoteHeatMap(userId));
    }
    @Override
    @NeedLogin
    public ApiResponse<Top3Count> submitNoteTop3Count() {

        Long userId = requestScopeData.getUserId();

        Top3Count top3Count = noteMapper.submitNoteTop3Count(userId);

        return ApiResponseUtil.success("获取笔记top3成功", top3Count);
    }


}
